import { COMPARE_STAGE, Stage } from './stage';
import { DefaultLoadingScreen } from '../loader/default-loading-screen';


/**
 * 舞台管理组件
 */
class StageManager {

    private _stages: Array<Stage> = [];
    private _previousStage: Stage | null = null;
    private _currentStage: Stage | null = null;
    private _currentGestureCount: number = 0;
    private _readyStageCount = 0;

    public get stages(): Stage[] {
        return this._stages;
    }

    /**
     * 循环渲染
     */
    public render(): void {
        if (this._currentStage) {
            if (this._currentStage.prepared) this._currentStage.render();
        }
    }

    /**
     * 窗体变化时执行
     * @param rect 矩形尺寸
     */
    public onWindowResize(rect: DOMRect): void {
        for (const stage of this._stages) {
            stage.onWindowResize(rect);
            stage.onWindowResizeObservable.notifyObservers(rect);
        }
    }

    /**
     * 已激活舞台的用户行为
     */
    public onUserGesture(): void {
        const stage = this._currentStage;
        if (!stage) return;
        if (!stage.prepared) return;
        const firstUserGesture = this._currentGestureCount === 0;
        stage.onUserGesture(firstUserGesture);
        stage.onUserGestureObservable.notifyObservers(firstUserGesture);
        this._currentGestureCount++;
    }

    /**
     * 获取舞台在舞台集合中的索引
     * @param stage 舞台
     * @returns 索引
     */
    public getStageIndex(stage: string | Stage | null): number {
        if (!stage) return -1;
        const spc = this.getStage(stage)!;
        return this._stages.findIndex(stg => COMPARE_STAGE(spc, stg));
    }

    /**
     * 添加舞台到管理组件集合
     * @param stages 舞台集合
     */
    public add(...stages: Array<Stage>): void {
        for (let stg of stages) {
            if (this._stages.find(sg => COMPARE_STAGE(sg, stg))) {
                console.warn('cannot add a stage for twice!');
                continue;
            }
            this._stages.push(stg);
            stg.onReady = () => {
                this._readyStageCount++;
                if (this._stages.length > this._readyStageCount) {
                    DefaultLoadingScreen.displayLoadingUI();
                } else {
                    DefaultLoadingScreen.hideLoadingUI();
                }
            };
        }
    }

    /**
     * 从舞台管理组件集合移除舞台
     * @param stages 舞台集合（舞台，或舞台ID，或舞台名称，或舞台在管理器集合中的索引）
     */
    public remove(...stages: Array<number | string | Stage>): void {
        for (let stage of stages) {
            const stg = this.getStage(stage);
            if (!stg) continue;
            const idx = this._stages.findIndex(sg => COMPARE_STAGE(sg, stg));
            this._stages.splice(idx, 1);
        }
        if (this._previousStage) {
            if (!this._stages.find(sg => COMPARE_STAGE(sg, this._previousStage!))) {
                this._previousStage = null;
            }
        }
        if (this._currentStage) {
            if (!this._stages.find(sg => COMPARE_STAGE(sg, this._currentStage!))) {
                this._currentStage.enable = false;
                this._currentStage = null;
            }
        }
    }

    /**
     * 启用舞台
     * @param stage 舞台，或舞台ID，或舞台名称，或舞台在管理器集合中的索引 
     */
    public enable(stage: number | string | Stage): void {
        const stg = this.getStage(stage);
        if (!stg) return;
        if (this._currentStage) {
            if (COMPARE_STAGE(stg, this._currentStage)) return;
            this._previousStage = this._currentStage;
            this._currentStage.enable = false;
            this._currentStage = stg;
            this._currentStage!.enable = true;
        } else {
            this._previousStage = null;
            this._currentStage = stg;
            this._currentStage!.enable = true;
        }
        this._currentGestureCount = 0;
    }

    /**
     * 禁用舞台
     * @param stage 舞台，或舞台ID，或舞台名称，或舞台在管理器集合中的索引 
     */
    public disable(stage: number | string | Stage): void {
        if (!this._currentStage) return;
        const stg = this.getStage(stage);
        if (!stg) return;
        if (!COMPARE_STAGE(this._currentStage, stg)) return;
        this._previousStage = this._currentStage;
        this._currentStage.enable = false;
        this._currentStage.onActiveObservable.notifyObservers(false);
        this._currentStage = null;
    }

    /**
     * 获取舞台
     * @param stage 舞台，或舞台ID，或舞台名称，或舞台在管理器集合中的索引  
     * @returns 舞台（可为null）
     */
    private getStage(stage: number | string | Stage): Stage | null {
        if (typeof stage === 'number') {
            const stg = this._stages[stage];
            if (stg) return stg;
        } else if (typeof stage === 'string') {
            for (let stg of this._stages) {
                if (stg.id === stage) return stg;
                if (stg.name === stage) return stg;
            }
        } else {
            for (let stg of this._stages) {
                if (COMPARE_STAGE(stg, stage)) return stg;
            }
        }
        return null;
    }

}

export { StageManager };
